﻿<!DOCTYPE html>
<html>
	<head>
		<title>Terrain Demo</title>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<link rel="stylesheet" href="webgl.css" type="text/css">
		<script src="SmitearWebGL/utils/stats.js" type="text/javascript"></script>
		<script src="SmitearWebGL/smitearwebgl.js" type="text/javascript"></script>
		<script src="SmitearWebGL/core/basic.js" type="text/javascript"></script>
		<script src="SmitearWebGL/core/algorithm/perlinnoise.js" type="text/javascript"></script>
		<script src="SmitearWebGL/scene/quadtree.js" type="text/javascript"></script>
		<script src="SmitearWebGL/scene/quadtreenode.js" type="text/javascript"></script>
		<script src="SmitearWebGL/scene/quadtreerect.js" type="text/javascript"></script>
		<script src="SmitearWebGL/scene/scene.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/bitmap.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/buffer.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/vertexbuffer.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/indexbuffer.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/bitmap.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/texture.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/texture2d.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/texturecube.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/shader.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/surfacematerial.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/resourceItem.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/resourcePool.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/resourcemanager.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/materiallayer.js" type="text/javascript"></script>
		<script src="SmitearWebGL/resources/rendersurface.js" type="text/javascript"></script>
		<script src="SmitearWebGL/programs/programmanager.js" type="text/javascript"></script>
		<script src="SmitearWebGL/render/renderqueue.js" type="text/javascript"></script>
		<script src="SmitearWebGL/render/rendersystem.js" type="text/javascript"></script>
		<script src="SmitearWebGL/render/renderer.js" type="text/javascript"></script>
		<script src="SmitearWebGL/render/lpprenderer.js" type="text/javascript"></script>
		<script src="SmitearWebGL/render/hdrrenderer.js" type="text/javascript"></script>
		<script src="SmitearWebGL/objects/container.js" type="text/javascript"></script>
		<script src="SmitearWebGL/objects/mesh.js" type="text/javascript"></script>
		<script src="SmitearWebGL/objects/shadowmesh.js" type="text/javascript"></script>
		<script src="SmitearWebGL/objects/terrain/terrainsystem.js" type="text/javascript"></script>
		<script src="SmitearWebGL/objects/terrain/terrainsection.js" type="text/javascript"></script>
		<script type="text/javascript">
			var stats, scene, camera, bitmap, terrain;
			var material, material2, material3, path, sampler;
			var lights = [], lSpheres = [], defaultNumLights = 1, nt = 0;
			var degree = 0;
			
			if ( SmitearWebGL.init( 1024, 512 ) ) 
			{
				window.onload = function() { applicationStart() };
				window.onerror = function() { onError() };
			}
			
			function applicationStart()
			{
				stats = new Stats();
				document.getElementById( "glstatus" ).appendChild( stats.domElement );
				document.getElementById( "glcanvas" ).appendChild( $DISPLAY_INFO.canvas );
				
				document.getElementById("numLights").value = defaultNumLights;
				document.getElementById("ssao_enable").checked = false;
				document.getElementById("hdr_enable").checked = false;
				document.getElementById("tex_enable").checked = false;
				document.getElementById("sha_enable").checked = false;
				document.getElementById("vol_enable").checked = false;
				
				$import("SmitearWebGL.Objects.Camera");
				$import("SmitearWebGL.Scene.Scene");
				$import("SmitearWebGL.Objects.Entity");
				$import("SmitearWebGL.Objects.Light");
				$import("SmitearWebGL.Objects.Primitive.Sphere");
				$import("SmitearWebGL.Objects.Terrain.TerrainSystem");

				camera = new SmitearWebGL.Objects.Camera("camera", 45.0, $DISPLAY_INFO.width / $DISPLAY_INFO.height, 0.1, 1000.0);
				camera.setX(0);
				camera.setY(10);
				camera.setZ(8);
				camera.rotateX(-45);
				camera.setTarget($V3(0.0, 0.0, 0.0));
				
				scene = new SmitearWebGL.Scene.Scene(2000, 500, 2000);
				scene.addEventListener( SmitearWebGL.Events.Event.FRAME_MOVE, this, this.onFrameMove );
				SmitearWebGL.Scene.setAmbient( $C( 1.0, 1.0, 1.0, 1.0 ) );
				
				path = new SmitearWebGL.Objects.Entity( "path" );
				scene.addChild(path);
				
				addLights(defaultNumLights);
				setupMaterial();
				
				bitmap = g_bitmapManager.createResource( "bitmap_" );
//				var pixels = new Array(8*8*4);
//				for ( var i = 0; i < 8*8*4; i += 4 )
//				{
//					pixels[i+0] = 128;
//					pixels[i+1] = 255;
//					pixels[i+2] = 255;
//					pixels[i+3] = 255;
//				}
				bitmap.createBitmap(512, 512, true, null);
				
				bitmap.generatePerlinNoise(8, 0.5, SmitearWebGL.Core.Algorithm.PerlinNoise.Type.FBM);
//				bitmap.generatePerlinNoise(8, 0.5, SmitearWebGL.Core.Algorithm.PerlinNoise.Type.NOISE);
//				bitmap.generatePerlinNoise(8, 0.5, SmitearWebGL.Core.Algorithm.PerlinNoise.Type.TURBLUENCE);
//				bitmap.generatePerlinNoise(8, 0.5, SmitearWebGL.Core.Algorithm.PerlinNoise.Type.RIDGEDMF);

//				document.getElementById("test").appendChild( bitmap._canvas );
//
//				h = new Array(4*4);
//				bitmap.generateHeightTable(h);
//				
//				n = new Array(4*4*3);
//				for ( var i = 0; i < n.length; i += 3 )
//				{
//					n[i+0] = 0.0;
//					n[i+1] = 1.0;
//					n[i+2] = 0.0;
//				}
//				bitmap.generateNormalTable(n);
				
				terrain = new SmitearWebGL.Objects.Terrain.TerrainSystem( "terrainSystem", bitmap, 60, 24, 60, 6 );
				terrain.setMaterial( material3 );
//				terrain.setZ(-0.1);
				scene.addChild(terrain);
				
				$DISPLAY_INFO.canvas.addEventListener("mousedown", handleMouseDown, false);
				$DISPLAY_INFO.canvas.addEventListener("mouseup", handleMouseUp, false);
				$DISPLAY_INFO.canvas.addEventListener("mousemove", handleMouseMove, false);
				window.addEventListener('keydown', handleKeyDown, true);
				window.addEventListener('keyup', handleKeyUp, true);
				
				scene.render(camera, 60);
			}
			
			function onFrameMove( e )
			{
				stats.update( scene );
			}
			
			function onError()
			{
				scene.stopRendering();
				return true;
			}
			
			function addLights(numLights)
			{
				var handle;
				var light;
				var lSphere;
				var lMat;

				for ( var i = 0; i < numLights; ++ i )
				{
					var r = Math.random();
					var g = Math.random();
					var b = Math.random();
					light = new SmitearWebGL.Objects.Light("light_" + nt);
					light.type = SmitearWebGL.Objects.Light.L_POINT;
					light.baseColor = $C(1.0, 0.5, 0.0, 1.0);
					light.intensity = 1.0;
					light.constantAttenuation = 0.5;
					light.linearAttenuation = 0.005;
					light.quadraticAttenuation = 0.001;
					light.setInnerCone(32.0);
					light.setOuterCone(60.0);
					light.spotExponent = 4.0;
					light.setY(5);
//					light.setX(getRandom(2, 3.0));
//					light.setY(getRandom(2, 3.0));
//					light.setZ(getRandom(2, 3.0));
					light.setDirectionX(Math.random()*2-1);
					light.setDirectionY(Math.random()*2-1);
					light.setDirectionZ(Math.random()*2-1);
					light.speed = Math.random()*2-1;
					path.addChild(light);
					lights.push(light);

					lMat = g_materialManager.createResource("__light_material__" + nt);
					lMat.ambient = $C( 0.1, 0.1, 0.1, 1.0 );
					lMat.diffuse = $C( 0.0, 0.0, 0.0, 1.0 );
					lMat.specular = $C( 0.0, 0.0, 0.0, 1.0 );
					lMat.emissive = light.baseColor;

					var lSphere = new SmitearWebGL.Objects.Primitive.Sphere("__light_entity__" + nt, 0.1, 8, 6);
					lSphere.setMaterial(lMat);
					lSphere.backFaceCulling = true;
					lSphere.setX( light.getX() );
					lSphere.setY( light.getY() );
					lSphere.setZ( light.getZ() );
					path.addChild(lSphere);
					lSpheres.push(lSphere);

					nt ++;
				}
			}

			function removeLights(numLights)
			{
				if ( numLights > lights.length )
				numLights = lights.length;

				var total = lights.length - 1;
				var end = lights.length - numLights;

				for ( var i = total; i >= end; -- i )
				{
					path.removeChild(lights[i]);
					path.removeChild(lSpheres[i]);
					lights.pop().release();
					lSpheres.pop().release();
				}
			}

			function getRandom(a, b)
			{
				var result = Math.random() * b + a;
				var rd = Math.random();
				if ( rd > .5)
				return result;
				else
				return - result;
			}

			//////////////////////////////// interactive //////////////////////////////

			var mouseDown = false;
			var lastMouseX = 0, lastMouseY = 0;
			var speed = 0.01;

			function handleMouseDown(event)
			{
				mouseDown = true;
				lastMouseX = event.clientX;
				lastMouseY = event.clientY;
			}

			function handleMouseUp(event)
			{
				mouseDown = false;
			}

			function handleMouseMove(event)
			{
				if ( mouseDown )
				{
					var newX = event.clientX;
					var newY = event.clientY;

					var mouseX = (newX - lastMouseX) * 0.05;
					var mouseY = (newY - lastMouseY) * 0.05;
					camera.upward(mouseY);
					camera.leftward(mouseX);

					lastMouseX = newX;
					lastMouseY = newY;
				}
			}
			
			function setupMaterial()
			{
				sampler = g_samplerManager.createResource("sampler");

				//texture for skybox
				material2 = g_materialManager.createResource("material2");
				material2.ambient = $C( 0.3, 0.3, 0.3, 1.0 );
				material2.diffuse = $C( 0.7, 0.7, 0.7, 1.0 );
				material2.specular = $C( 0.2, 0.2, 0.2, 1.0 );
				material2.emissive = $C( 0.0, 0.0, 0.0, 1.0 );
				material2.shininess = 32.0;
				material2.doubleSide = false;

				var cubemapTex = g_textureCubeManager.createResource("media/cubemap/CubemapCross.png");
				cubemapTex.addEventListener( SmitearWebGL.Resources.Texture.LOAD_COMPLETE, this, this.textureCompleteHandler);
				cubemapTex.load("media/cubemap/CubemapCross.png");
				var layer = g_materialLayerManager.createResource("materialLayer");
				layer.mapinput = SmitearWebGL.Resources.MaterialLayer.UV1;
				layer.mapToDiffuse(true);
				layer.mapToSpecular(false);
				layer.mapToEmissive(false);
				layer.setTexture(cubemapTex);
				material2.addLayer(layer);

				//multply woodTex
				material = g_materialManager.createResource("material");
				material.ambient = $C( 0.3, 0.3, 0.3, 1.0 );
				material.diffuse = $C( 0.8, 0.8, 0.8, 1.0 );
				material.specular = $C( 0.8, 0.8, 0.8, 1.0 );
				material.emissive = $C( 0.0, 0.0, 0.0, 1.0 );
				material.shininess = 8.0;
				material.doubleSide = true;

				var woodTex = g_texture2dManager.createResource("media/wood01.jpg");
				woodTex.addEventListener( SmitearWebGL.Resources.Texture.LOAD_COMPLETE, this, this.textureCompleteHandler);
				woodTex.load("media/wood01.jpg");
				layer = g_materialLayerManager.createResource("materialLayer2");
				layer.mapinput = SmitearWebGL.Resources.MaterialLayer.UV1;
				layer.mapToDiffuse(true);
				layer.mapToSpecular(false);
				layer.mapToEmissive(false);
				layer.setTexture(woodTex);
				material.addLayer(layer);

				var cubeTex = g_texture2dManager.createResource("media/cubetexture.png");
				cubeTex.load("media/cubetexture.png");
				cubeTex.addEventListener( SmitearWebGL.Resources.Texture.LOAD_COMPLETE, this, this.textureCompleteHandler);
				layer = g_materialLayerManager.createResource("materialLayer3");
				layer.mapinput = SmitearWebGL.Resources.MaterialLayer.UV1;
				layer.mapToDiffuse(true);
				layer.mapToSpecular(false);
				layer.mapToEmissive(false);
				layer.setTexture(cubeTex);
				material.addLayer(layer);
				
				//no texutre for ojbects
				material3 = g_materialManager.createResource("material3");
				material3.ambient = $C( 0.2, 0.2, 0.2, 1.0 );
				material3.diffuse = $C( 0.8, 0.8, 0.8, 1.0 );
				material3.specular = $C( 0.4, 0.4, 0.4, 1.0 );
				material3.emissive = $C( 0.0, 0.0, 0.0, 1.0 );
				material3.shininess = 12.0;
				material3.doubleSide = true;
			}
			
			function textureCompleteHandler(e)
			{
				var woodTex = e.sender;
				woodTex.removeEventListener(  SmitearWebGL.Resources.Texture.LOAD_COMPLETE, this.textureCompleteHandler );
				woodTex.bindSampler(sampler);
			}

			var isRendering = true;

			function handleKeyDown(event)
			{
				if (String.fromCharCode(event.keyCode) == "Q")
				{
					if ( isRendering )
					scene.stopRendering();
					else
					scene.render(camera, 60);

					isRendering = ! isRendering;
				}
				if (String.fromCharCode(event.keyCode) == "W")
				{
					camera.forward( 0.2 );
				}
				if (String.fromCharCode(event.keyCode) == "S")
				{
					camera.backward( 0.2 );
				}
				if (String.fromCharCode(event.keyCode) == "A")
				{
					camera.leftward( 0.2 );
				}
				if (String.fromCharCode(event.keyCode) == "D")
				{
					camera.rightward( 0.2 );
				}
			}

			function handleKeyUp(event)
			{
			}

			function btnDec_click()
			{
				var elem = document.getElementById("numLights");
				var num = parseInt(elem.value);
				if ( num == 0 ) return;
				-- num;
				elem.value = num.toString();

				removeLights( 1 );
			}

			function btnInc_click()
			{
				var elem = document.getElementById("numLights");
				var num = parseInt(elem.value);
				if ( num == 255 ) return;
				++ num;
				elem.value = num.toString();

				addLights( 1 );
			}

			function numLights_chnage(value)
			{
				var numToAddOrDel = value - lights.length;
				if ( numToAddOrDel > 0 )
				{
					addLights(numToAddOrDel);
				}
				else
				{
					removeLights(-numToAddOrDel);
				}
			}

			function ssaoEnable()
			{
				if ( document.getElementById("ssao_enable").checked )
				SmitearWebGL.Scene.enableSSAO();
				else
				SmitearWebGL.Scene.disableSSAO();
			}

			function ssaoParamChange()
			{
				var strength = document.getElementById("ssao_strength").value;
				var scale = document.getElementById("ssao_scale").value;
				var falloff = document.getElementById("ssao_falloff").value;
				var rad = document.getElementById("ssao_rad").value;

				document.getElementById("ssao_strength_v").innerHTML = strength;
				document.getElementById("ssao_scale_v").innerHTML = scale;
				document.getElementById("ssao_falloff_v").innerHTML = falloff;
				document.getElementById("ssao_rad_v").innerHTML = rad;

				SmitearWebGL.Scene.setSSAOParam(strength, scale, falloff, rad );
			}

			function hdrEnable()
			{
				if ( document.getElementById("hdr_enable").checked )
				SmitearWebGL.Scene.enableHDR();
				else
				SmitearWebGL.Scene.disableHDR();
			}

			function hdrParamChange()
			{
				var threshold = document.getElementById("hdr_threshold").value;
				var gaussMultiplier = document.getElementById("hdr_gaussMultiplier").value;
				var gaussMean = document.getElementById("hdr_gaussMean").value;
				var gaussStdDev = document.getElementById("hdr_gaussStdDev").value;
				var exposure = document.getElementById("hdr_exposure").value;

				document.getElementById("hdr_threshold_v").innerHTML = threshold;
				document.getElementById("hdr_gaussMultiplier_v").innerHTML = gaussMultiplier;
				document.getElementById("hdr_gaussMean_v").innerHTML = gaussMean;
				document.getElementById("hdr_gaussStdDev_v").innerHTML = gaussStdDev;
				document.getElementById("hdr_exposure_v").innerHTML = exposure;

				SmitearWebGL.Scene.setHDRParam(threshold, gaussMultiplier, gaussMean, gaussStdDev, exposure );
			}
			
			var texEnable = false;
			function textureEnable()
			{
				if ( ! texEnable )
				{
					terrain.setMaterial(material);
				}
				else
				{
					terrain.setMaterial(material3);
				}
				texEnable = ! texEnable;
			}
			
			var _shadowEnable = false;
			function shadowEnable()
			{
				if ( ! _shadowEnable )
				{
					SmitearWebGL.Scene.enableShadow();
				}
				else
				{
					SmitearWebGL.Scene.disableShadow();
				}
				_shadowEnable = ! _shadowEnable;
			}
			
			var _showShadowVolume = false;
			function showShadowVolume()
			{
				if ( ! _showShadowVolume )
				{
					SmitearWebGL.Scene.showShadowVolume();
				}
				else
				{
					SmitearWebGL.Scene.hideShadowVolume();
				}
				_showShadowVolume = ! _showShadowVolume;
			}
			
			function pointEnable()
			{
				material.renderMode = SmitearWebGL.Resources.SurfaceMaterial.renderMode.POINT;
				material2.renderMode = SmitearWebGL.Resources.SurfaceMaterial.renderMode.POINT;
				material3.renderMode = SmitearWebGL.Resources.SurfaceMaterial.renderMode.POINT;
			}
			
			function wireFrameEnable()
			{
				material.renderMode = SmitearWebGL.Resources.SurfaceMaterial.renderMode.WIREFRAME;
				material2.renderMode = SmitearWebGL.Resources.SurfaceMaterial.renderMode.WIREFRAME;
				material3.renderMode = SmitearWebGL.Resources.SurfaceMaterial.renderMode.WIREFRAME;
			}
			
			function triangleEnable()
			{
				material.renderMode = SmitearWebGL.Resources.SurfaceMaterial.renderMode.TRIANGLE;
				material2.renderMode = SmitearWebGL.Resources.SurfaceMaterial.renderMode.TRIANGLE;
				material3.renderMode = SmitearWebGL.Resources.SurfaceMaterial.renderMode.TRIANGLE;
			}
		</script>
	</head>
	<body>
		<div class="webglContent">
			<div id="glstatus" class="stats-css"></div>
			<div id="glcanvas" class="gl-css shadow"></div>
			<div id="control" class="shadow radius-border">
				<div id="wireframe">
					<div><span>Point Mode</span><input id="point_enable" name="select_role" type="radio" checked="" onclick="pointEnable();"/></div>
					<div><span>WireFrame Mode</span><input id="wire_enable" name="select_role" type="radio" checked="" onclick="wireFrameEnable();"/></div>
					<div><span>Triangle Mode</span><input id="triangle_enable" name="select_role" type="radio" checked="true" onclick="triangleEnable();"/></div>
					<hr />
				</div>
				<div id="texutre">
					<div><span>Enable texture</span><input id="tex_enable" type="checkbox" checked="" onclick="textureEnable();"/></div>
					<hr />
				</div>
				<div id="shadow">
					<div><span>Enable shadow</span><input id="sha_enable" type="checkbox" checked="" onclick="shadowEnable();"/></div>
					<div><span>Show Shadow Volume</span><input id="vol_enable" type="checkbox" checked="false" onclick="showShadowVolume();"/></div>
					<hr />
				</div>
				<div id="lighting">
					Light number:
					<button type="button" id="btnDec" onclick="btnDec_click();">-</button>
					<input id="numLights" value="0" style="width:20px;" onchange="numLights_chnage(parseInt(this.value));"/>
					<button type="button" id="btnInc" onclick="btnInc_click();">+</button>
					<hr />
				</div>
				<div id="ssao">
					<div><span>Enable SSAO</span><input id="ssao_enable" type="checkbox" checked="" onclick="ssaoEnable();"/></div>
					<div><span>Strength</span><input id="ssao_strength" type="range" min="0.0" max="10.0" value="1.0" step="0.5" onchange="ssaoParamChange()";/><span id="ssao_strength_v">0</span></div>
					<div><span>Scale</span><input id="ssao_scale" type="range" min="10.0" max="100.0" value="90.0" step="5.0" onchange="ssaoParamChange()";/><span id="ssao_scale_v">0</span></div>
					<div><span>Falloff</span><input id="ssao_falloff" type="range" min="-0.01" max="0.01" value="0.000002" step="0.001" onchange="ssaoParamChange()";/><span id="ssao_falloff_v">0</span></div>
					<div><span>Rad</span><input id="ssao_rad" type="range" min="0.00005" max="0.0003" value="0.00005" step="0.00005" onchange="ssaoParamChange()";/><span id="ssao_rad_v">0</span></div>
					<hr />
				</div>
				<div id="hdr">
					<div><span>Enable HDR</span><input id="hdr_enable" type="checkbox" checked="" onclick="hdrEnable();"/></div>
					<div><span>Threshold</span><input id="hdr_threshold" type="range" min="0" max="1.0" value="0.9" step="0.01" onchange="hdrParamChange()";/><span id="hdr_threshold_v">0</span></div>
					<div><span>GaussMultiplier</span><input id="hdr_gaussMultiplier" type="range" min="0" max="1.0" value="0.25" step="0.01" onchange="hdrParamChange()";/><span id="hdr_gaussMultiplier_v">0</span></div>
					<div><span>GaussMean</span><input id="hdr_gaussMean" type="range" min="0" max="1.0" value="0.0" step="0.01" onchange="hdrParamChange()";/><span id="hdr_gaussMean_v">0</span></div>
					<div><span>GaussStdDev</span><input id="hdr_gaussStdDev" type="range" min="0" max="1.0" value="0.68" step="0.01" onchange="hdrParamChange()";/><span id="hdr_gaussStdDev_v">0</span></div>
					<div><span>Exposure</span><input id="hdr_exposure" type="range" min="0" max="1.0" value="0.4" step="0.01" onchange="hdrParamChange()";/><span id="hdr_exposure_v">0</span></div>
				</div>
			</div>
		</div>
		<div id="test"></div>
	</body>
</html>
